import OSS from 'ali-oss';
import { ossConfig, validateOSSConfig } from '../config/oss';
import path from 'path';
import fs from 'fs/promises';

export interface UploadResult {
  success: boolean;
  url?: string;
  key?: string;
  error?: string;
}

export interface ListObjectsOptions {
  prefix?: string;
  maxKeys?: number;
  marker?: string;
}

export class OSSService {
  private client: OSS | null = null;
  private isInitialized = false;

  constructor() {
    this.initialize();
  }

  private initialize(): void {
    if (!validateOSSConfig()) {
      throw new Error('OSS配置验证失败');
    }

    try {
      this.client = new OSS({
        region: ossConfig.region,
        accessKeyId: ossConfig.accessKeyId,
        accessKeySecret: ossConfig.accessKeySecret,
        bucket: ossConfig.bucket,
        endpoint: ossConfig.endpoint
      });
      
      this.isInitialized = true;
      console.log('OSS客户端初始化成功');
    } catch (error) {
      console.error('OSS客户端初始化失败:', error);
      throw error;
    }
  }

  private ensureInitialized(): void {
    if (!this.isInitialized || !this.client) {
      throw new Error('OSS客户端未正确初始化');
    }
  }

  /**
   * 上传文件到OSS
   * @param filePath 本地文件路径
   * @param objectKey OSS中的对象键（文件路径）
   * @returns 上传结果
   */
  async uploadFile(filePath: string, objectKey: string): Promise<UploadResult> {
    try {
      this.ensureInitialized();

      // 检查本地文件是否存在
      try {
        await fs.access(filePath);
      } catch {
        return {
          success: false,
          error: `本地文件不存在: ${filePath}`
        };
      }

      const result = await this.client!.put(objectKey, filePath);
      
      return {
        success: true,
        url: result.url,
        key: objectKey
      };
    } catch (error) {
      console.error('文件上传失败:', error);
      return {
        success: false,
        error: error instanceof Error ? error.message : '上传失败'
      };
    }
  }

  /**
   * 上传Buffer到OSS
   * @param buffer 文件Buffer
   * @param objectKey OSS中的对象键（文件路径）
   * @returns 上传结果
   */
  async uploadBuffer(buffer: Buffer, objectKey: string): Promise<UploadResult> {
    try {
      this.ensureInitialized();

      const result = await this.client!.put(objectKey, buffer);
      
      return {
        success: true,
        url: result.url,
        key: objectKey
      };
    } catch (error) {
      console.error('Buffer上传失败:', error);
      return {
        success: false,
        error: error instanceof Error ? error.message : '上传失败'
      };
    }
  }

  /**
   * 删除OSS中的文件
   * @param objectKey OSS中的对象键
   * @returns 删除结果
   */
  async deleteFile(objectKey: string): Promise<{ success: boolean; error?: string }> {
    try {
      this.ensureInitialized();

      await this.client!.delete(objectKey);
      
      return { success: true };
    } catch (error) {
      console.error('文件删除失败:', error);
      return {
        success: false,
        error: error instanceof Error ? error.message : '删除失败'
      };
    }
  }

  /**
   * 批量删除OSS中的文件
   * @param objectKeys OSS中的对象键数组
   * @returns 删除结果
   */
  async deleteMultipleFiles(objectKeys: string[]): Promise<{
    success: boolean;
    deleted?: string[];
    error?: string;
  }> {
    try {
      this.ensureInitialized();

      const result = await this.client!.deleteMulti(objectKeys);
      
      return {
        success: true,
        deleted: result.deleted || []
      };
    } catch (error) {
      console.error('批量删除失败:', error);
      return {
        success: false,
        error: error instanceof Error ? error.message : '批量删除失败'
      };
    }
  }

  /**
   * 获取文件的签名URL（用于私有文件访问）
   * @param objectKey OSS中的对象键
   * @param expires 过期时间（秒）
   * @returns 签名URL
   */
  async getSignedUrl(objectKey: string, expires: number = 3600): Promise<{
    success: boolean;
    url?: string;
    error?: string;
  }> {
    try {
      this.ensureInitialized();

      const url = this.client!.signatureUrl(objectKey, { expires: expires * 1000 });
      
      return {
        success: true,
        url
      };
    } catch (error) {
      console.error('获取签名URL失败:', error);
      return {
        success: false,
        error: error instanceof Error ? error.message : '获取签名URL失败'
      };
    }
  }

  /**
   * 列举OSS中的文件
   * @param options 列举选项
   * @returns 文件列表
   */
  async listObjects(options: ListObjectsOptions = {}): Promise<{
    success: boolean;
    objects?: OSS.ObjectMeta[];
    nextMarker?: string;
    error?: string;
  }> {
    try {
      this.ensureInitialized();

      const query: OSS.ListObjectsQuery = {
        'max-keys': options.maxKeys || 100,
        ...(options.prefix && { prefix: options.prefix }),
        ...(options.marker && { marker: options.marker })
      };
      
      const result = await this.client!.list(query, {});
      
      return {
        success: true,
        objects: result.objects,
        nextMarker: result.nextMarker
      };
    } catch (error) {
      console.error('列举文件失败:', error);
      return {
        success: false,
        error: error instanceof Error ? error.message : '列举文件失败'
      };
    }
  }

  /**
   * 检查文件是否存在
   * @param objectKey OSS中的对象键
   * @returns 是否存在
   */
  async exists(objectKey: string): Promise<{ success: boolean; exists?: boolean; error?: string }> {
    try {
      this.ensureInitialized();

      const result = await this.client!.head(objectKey);
      
      return {
        success: true,
        exists: !!result
      };
    } catch (error: any) {
      if (error.code === 'NoSuchKey') {
        return {
          success: true,
          exists: false
        };
      }
      
      console.error('检查文件存在性失败:', error);
      return {
        success: false,
        error: error instanceof Error ? error.message : '检查失败'
      };
    }
  }

  /**
   * 生成带时间戳的文件名
   * @param originalName 原始文件名
   * @param prefix 前缀路径
   * @returns 新的文件名
   */
  generateFileName(originalName: string, prefix: string = 'uploads'): string {
    const ext = path.extname(originalName);
    const name = path.basename(originalName, ext);
    const timestamp = Date.now();
    const random = Math.random().toString(36).substring(2, 8);
    
    return `${prefix}/${timestamp}-${random}-${name}${ext}`;
  }

  /**
   * 获取所有存储桶列表
   * @returns 存储桶列表
   */
  async listBuckets(): Promise<{
    success: boolean;
    buckets?: OSS.Bucket[];
    error?: string;
  }> {
    try {
      this.ensureInitialized();

      const result = await this.client!.listBuckets({});
      
      return {
        success: true,
        buckets: (result as any).buckets || []
      };
    } catch (error) {
      console.error('列举存储桶失败:', error);
      return {
        success: false,
        error: error instanceof Error ? error.message : '列举存储桶失败'
      };
    }
  }
}

// 导出单例实例
export const ossService = new OSSService();